﻿#include "cctprequestmode.h"
#include "ctpdatastorage.h"
#include<QDir>
#include"../CommUtil/ComFun.h"

CCTPRequestMode::CCTPRequestMode(void)
{
    m_strUserName = "17080000";
    m_strBrokerID = "8888";
    m_strPassword = "112019";

    //m_strUserName = "18900700";
    //m_strBrokerID = "8888";
    //m_strPassword = "123654";

    m_DaoName = "CCTPRequestMode";
    m_Dao     = new OracleDAO(m_DaoName);

    CComFun::LogFileInit();
}

CCTPRequestMode::~CCTPRequestMode(void)
{
    CComFun::LogFileRelease();
}

void CCTPRequestMode::InitTradeObject(){
    QDir dir;
    QString currentPath=dir.currentPath();
    QString sParentDir = currentPath;
    QString sTradeDir;

    //创建TradeCon文件的目录
    sParentDir.append("/").append(m_strUserName);
    sTradeDir = sParentDir;
    sTradeDir.append("/TradeCon");

    if (!dir.exists(sParentDir))
    {
        if (!dir.mkdir(sParentDir))
        {
            std::cout << "ERROR: Create TradeCon Failure"<< std::endl;
        }
    }

    if (!dir.exists(sTradeDir))
    {
        if (!dir.mkdir(sTradeDir))
        {
            std::cout << "ERROR: Fail To Create TradeConDir"<< std::endl;
        }
    }

    sTradeDir = sTradeDir + "/";

    //初始化交易服务器
    m_pTradeUserApi = CThostFtdcTraderApi::CreateFtdcTraderApi(sTradeDir.toStdString().c_str());
    m_pThostFtdcTraderSpiImpl = new CThostFtdcTraderSpiImpl();
    m_pThostFtdcTraderSpiImpl->SetUserApi(m_pTradeUserApi);

    m_pThostFtdcTraderSpiImpl->SetUserAndPassword(m_strBrokerID,m_strUserName,m_strPassword);
    m_pThostFtdcTraderSpiImpl->SetCTPRequestMode(this);
    m_pTradeUserApi->RegisterSpi((CThostFtdcTraderSpi*)m_pThostFtdcTraderSpiImpl);

    m_pTradeUserApi->SubscribePublicTopic(THOST_TERT_RESTART);
    m_pTradeUserApi->SubscribePrivateTopic(THOST_TERT_QUICK);
}

void CCTPRequestMode::InitMdObject(){
    QDir dir;
        QString currentPath=dir.currentPath();
        QString sParentDir = currentPath;
        QString sMdDir;

        //创建MdCon文件的目录
        sParentDir.append("/").append(m_strUserName);
        sMdDir = sParentDir;
        sMdDir.append("/MdCon");

        if (!dir.exists(sParentDir))
        {
            if (!dir.mkdir(sParentDir))
            {
                std::cout << "ERROR: Create MdCon Failure"<< std::endl;
            }
        }

        if (!dir.exists(sMdDir))
        {
            if (!dir.mkdir(sMdDir))
            {
                std::cout << "ERROR: Fail To Create MdConDir"<< std::endl;
            }
        }
        sMdDir = sMdDir + "/";

        //初始化行情服务器
        m_pmdUserApi = CThostFtdcMdApi::CreateFtdcMdApi(sMdDir.toStdString().c_str());
        m_pThostFtdcMdSpiImpl = new CThostFtdcMdSpiImpl();
        m_pThostFtdcMdSpiImpl->SetUserApi(m_pmdUserApi);
        m_pThostFtdcMdSpiImpl->SetUserAndPassword(m_strBrokerID,m_strUserName,m_strPassword);
        m_pThostFtdcMdSpiImpl->SetCTPRequestMode(this);
        m_pmdUserApi->RegisterSpi((CThostFtdcMdSpi *)m_pThostFtdcMdSpiImpl);
}

void CCTPRequestMode::ConnectToMdServer(){
    //QString qstrMdFront    = "tcp://140.206.103.249:41213";//仿真行情
    QString strCUCCMdFront    = "tcp://140.206.103.242:41213";//联通 实盘行情
    QString strCTCCMdFront    = "tcp://180.166.183.113:41213";//电信 实盘行情

    char* pszCUCCMdFront,*pszCTCCMdFront;
    pszCUCCMdFront=strCUCCMdFront.toLatin1().data();
    pszCTCCMdFront=strCTCCMdFront.toLatin1().data();

    //注册行情前置 多前置注册 API会自动选择速度快的前置机
    m_pmdUserApi->RegisterFront(pszCUCCMdFront);//注册联通前置
    m_pmdUserApi->RegisterFront(pszCTCCMdFront);//注册电信前置
    m_pmdUserApi->Init();
}

void CCTPRequestMode::ConnectToTradeServer(){
    //QString qstrTradeFront("tcp://140.206.103.249:41205");
    QString strCUCCTradeFront   = "tcp://140.206.103.242:41205";//联通前置 实盘交易
    QString strCTCCTradeFront   = "tcp://180.166.183.113:41205";//电信前置 实盘交易

    char*  pszCUCCTradeFront,*pszCTCCTradeFront;
    pszCUCCTradeFront=strCUCCTradeFront.toLatin1().data();
    pszCTCCTradeFront=strCTCCTradeFront.toLatin1().data();

    //注册交易前置 多前置注册 API会自动选择速度快的前置机
    m_pTradeUserApi->RegisterFront(pszCUCCTradeFront);//注册联通前置
    m_pTradeUserApi->RegisterFront(pszCTCCTradeFront);//注册电信前置
    m_pTradeUserApi->Init();
}

void CCTPRequestMode::SubscribeMarketData(){
    if(true == GetInstruments()){
        //订阅行情的合约数量和合约列表
        int iContractCount;
        char** Instruments;

        iContractCount = m_InstrumentsVector.size();
        if(iContractCount > 0 ){
            Instruments=new char*[iContractCount];

            for(int iLoop = 0; iLoop < iContractCount; iLoop++){
                QString Instr = m_InstrumentsVector[iLoop];

                char* Instrtmp = new char [sizeof(TThostFtdcInstrumentIDType)];
                strncpy(Instrtmp,Instr.toStdString().c_str(),sizeof(TThostFtdcInstrumentIDType));
                Instruments[iLoop]=Instrtmp;
            }

            CComFun::SleepSecs(10);

            m_pmdUserApi->SubscribeMarketData(Instruments,iContractCount);
            std::cout <<"SubscribeMarketData Success"<< std::endl;

            for(int i = 0; i < iContractCount; i++){
                delete Instruments[i];
            }
            delete Instruments;
            std::cout <<"Free Instruments Pointer Success"<< std::endl;

            CComFun::OutputMessage(QTime::currentTime().toString("hh:mm:ss") + " SubscribeMarketData Success");
        }else{
            std::cout <<"No Instruments Data"<< std::endl;
        }
    }
}

void CCTPRequestMode::StartSaveMarketInfoThrd(){
    for(int i=0; i < WORK_QUEUE; i++) {
        m_thrdSave[i].m_nIndex = i;
        m_thrdSave[i].m_szThrdName = "CTPSaveThrd" + QString::number(i);
        m_thrdSave[i].start();
    }
    ///创建一个新线程  来保存日K线数据
    m_thrdSave1Day.m_nIndex = WORK_QUEUE ;//not used
    m_thrdSave1Day.m_szThrdName = "CTPSaveDayKlineThrd";
    m_thrdSave1Day.start();
    ///创建一个新线程 来保存5分钟K线数据
    m_thrdSave5MinKLine.m_nIndex = WORK_QUEUE + 1;//not used
    m_thrdSave5MinKLine.m_szThrdName = "CTPSave5MinKlineThrd";
    m_thrdSave5MinKLine.start();
    ///创建一个新线程 来保存1分钟K线数据
    //m_thrdSave1MinKLine.m_nIndex = WORK_QUEUE + 2;//not used
    //m_thrdSave1MinKLine.m_szThrdName = "CTPSave1MinKlineThrd";
    //m_thrdSave1MinKLine.start();
}
bool CCTPRequestMode::GetInstruments(){
    m_InstrumentsVector.clear();
    return m_Dao->GetInstruments(m_DaoName,m_InstrumentsVector,m_contracttype);
}
bool CCTPRequestMode::MatchThread(){
    return m_Dao->MatchThread(m_DaoName,m_MapMatchThrd);
}
void CCTPRequestMode::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
{
    QStringList szHqList;
    szHqList << QString(pDepthMarketData->TradingDay);//0
    szHqList << QString(pDepthMarketData->InstrumentID);
    szHqList << QString(pDepthMarketData->ExchangeID);
    szHqList << QString(pDepthMarketData->ExchangeInstID);
    szHqList << QString::number(pDepthMarketData->LastPrice);
    szHqList << QString::number(pDepthMarketData->PreSettlementPrice);//5
    szHqList << QString::number(pDepthMarketData->PreClosePrice);
    szHqList << QString::number(pDepthMarketData->PreOpenInterest);
    szHqList << QString::number(pDepthMarketData->OpenPrice);
    szHqList << QString::number(pDepthMarketData->HighestPrice);
    szHqList << QString::number(pDepthMarketData->LowestPrice);//10
    szHqList << QString::number(pDepthMarketData->Volume);
    szHqList << QString::number(pDepthMarketData->Turnover);
    szHqList << QString::number(pDepthMarketData->OpenInterest);
    szHqList << QString::number(pDepthMarketData->ClosePrice);
    szHqList << QString::number(pDepthMarketData->SettlementPrice);//15
    szHqList << QString::number(pDepthMarketData->UpperLimitPrice);
    szHqList << QString::number(pDepthMarketData->LowerLimitPrice);
    szHqList << QString::number(pDepthMarketData->PreDelta);
    szHqList << QString::number(pDepthMarketData->CurrDelta);
    szHqList << QString(pDepthMarketData->UpdateTime);//20
    szHqList << QString::number(pDepthMarketData->UpdateMillisec);
    szHqList << QString::number(pDepthMarketData->BidPrice1);
    szHqList << QString::number(pDepthMarketData->BidVolume1);
    szHqList << QString::number(pDepthMarketData->AskPrice1);
    szHqList << QString::number(pDepthMarketData->AskVolume1);//25
    szHqList << QString::number(pDepthMarketData->BidPrice2);
    szHqList << QString::number(pDepthMarketData->BidVolume2);
    szHqList << QString::number(pDepthMarketData->AskPrice2);
    szHqList << QString::number(pDepthMarketData->AskVolume2);
    szHqList << QString::number(pDepthMarketData->BidPrice3);//30
    szHqList << QString::number(pDepthMarketData->BidVolume3);
    szHqList << QString::number(pDepthMarketData->AskPrice3);
    szHqList << QString::number(pDepthMarketData->AskVolume3);
    szHqList << QString::number(pDepthMarketData->BidPrice4);
    szHqList << QString::number(pDepthMarketData->BidVolume4);//35
    szHqList << QString::number(pDepthMarketData->AskPrice4);
    szHqList << QString::number(pDepthMarketData->AskVolume4);
    szHqList << QString::number(pDepthMarketData->BidPrice5);
    szHqList << QString::number(pDepthMarketData->BidVolume5);
    szHqList << QString::number(pDepthMarketData->AskPrice5);//40
    szHqList << QString::number(pDepthMarketData->AskVolume5);
    szHqList << QString::number(pDepthMarketData->AveragePrice);
    //UPD houzhj 20170421 start
    //大商所推送过来的ActionDay是交易日 而不是实际发生日
    //所以这里统一使用系统当前日期进行存储
    QString date = QDate::currentDate().toString("yyyyMMdd");//获取当前日期
    //szHqList << QString(pDepthMarketData->ActionDay);//43
    szHqList << QString(date);//43
    //UPD houzhj 20170421 start

    int iIndex = 0;
    if(m_MapMatchThrd.contains(QString(pDepthMarketData->InstrumentID))){
        iIndex = m_MapMatchThrd[QString(pDepthMarketData->InstrumentID)];
    }else{
        iIndex = CComFun::RandomNum(WORK_QUEUE - 1);
        m_MapMatchThrd.insert(QString(pDepthMarketData->InstrumentID),iIndex);
    }
    CTPDataStorage::SetData(szHqList, iIndex);
}
